home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / gnuchess.win / gnuchess / nondsp.c < prev    next >
C/C++ Source or Header  |  1992-07-03  |  26KB  |  1,117 lines

  1. /*
  2.   nondsp.c - UNIX & MSDOS NON-DISPLAY, AND CHESSTOOL interface for Chess
  3.  
  4.   Revision: 1990-04-18
  5.  
  6.   Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
  7.   Copyright (c) 1988, 1989, 1990  John Stanback
  8.  
  9.   This file is part of CHESS.
  10.  
  11.   CHESS is distributed in the hope that it will be useful, but WITHOUT ANY
  12.   WARRANTY.  No author or distributor accepts responsibility to anyone for
  13.   the consequences of using it or for whether it serves any particular
  14.   purpose or works at all, unless he says so in writing.  Refer to the CHESS
  15.   General Public License for full details.
  16.  
  17.   Everyone is granted permission to copy, modify and redistribute CHESS, but
  18.   only under the conditions described in the CHESS General Public License.
  19.   A copy of this license is supposed to have been given to you along with
  20.   CHESS so you can know your rights and responsibilities.  It should be in a
  21.   file named COPYING.  Among other things, the copyright notice and this
  22.   notice must be preserved on all copies.
  23. */
  24.  
  25. #include <ctype.h>
  26. #include <signal.h>
  27. #ifdef MSDOS
  28. #include <dos.h>
  29. #include <conio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <time.h>
  33. #else
  34. #include <sys/param.h>
  35. #include <sys/types.h>
  36. #include <sys/file.h>
  37. #include <sys/ioctl.h>
  38. void TerminateSearch (int), Die (int);
  39. #endif /* MSDOS */
  40.  
  41. #include "gnuchess.h"
  42. #include "autoint.h"   /*** auto addition ***/
  43.  
  44. #define pxx " PNBRQK"
  45. #define qxx " pnbrqk"
  46. #define rxx "12345678"
  47. #define cxx "abcdefgh"
  48. #define printz printf
  49. #define scanz scanf
  50.  
  51. char mvstr[4][6];  /*** auto alteration (static) ***/
  52. static char* ColorStr[2] = {"White", "Black"};
  53. static long evrate;
  54. static int mycnt1, mycnt2;
  55. static int ahead;
  56.  
  57. /***** auto.c addition *****/
  58. extern int autoplay;
  59.  
  60. void
  61. Initialize (void)
  62. {
  63.   mycnt1 = mycnt2 = 0;
  64. #ifdef CHESSTOOL
  65.  
  66.   /* Make sure stdout is line-buffered.  */
  67.  
  68. #if    defined(USGr3) || defined(HPUX) || defined(hpux)
  69.   setvbuf (stdout, (char *) 0, _IOLBF, BUFSIZ);
  70. #else    /* Not USGr3 and not HPUX.  */
  71. #ifdef    USG
  72.   setvbuf (stdout, _IOLBF, (char *) 0, BUFSIZ);
  73. #else    /* Not USG.  */
  74.   setlinebuf (stdout);
  75. #endif    /* USG.  */
  76. #endif    /* USGr3.  */
  77.  
  78.   printf ("Chess\n");
  79.   if (Level == 0 && !TCflag)
  80.     Level = 15;
  81. #endif /* CHESSTOOL */
  82. }
  83.  
  84. void
  85. ExitChess (void)
  86. {
  87.   ListGame ();
  88.   exit (0);
  89. }
  90.  
  91. #ifndef MSDOS                /* never called!!! */
  92. void
  93. Die (int sig)
  94. {
  95.   char s[80];
  96.   ShowMessage ("Abort? ");
  97.   scanz ("%s", s);
  98.   if (strcmp (s, "yes") == 0)
  99.     ExitChess ();
  100. }
  101. #endif /* MSDOS */
  102.  
  103. void
  104. TerminateSearch (int sig)
  105. {
  106. #ifdef MSDOS
  107.   sig++;                /* shut up the compiler */
  108. #endif /* MSDOS */
  109.   flag.timeout = true;
  110.   flag.bothsides = false;
  111. }
  112.  
  113. void
  114. algbr (short int f, short int t, short int flag)
  115.                       
  116.  
  117. /*
  118.    Generate move strings in different formats.
  119. */
  120.  
  121. {
  122.   int m3p;
  123.  
  124.   if (f != t)
  125.     {
  126.       /* algebraic notation */
  127.       mvstr[0][0] = cxx[column (f)];
  128.       mvstr[0][1] = rxx[row (f)];
  129.       mvstr[0][2] = cxx[column (t)];
  130.       mvstr[0][3] = rxx[row (t)];
  131.       mvstr[0][4] = mvstr[3][0] = '\0';
  132.       if ((mvstr[1][0] = pxx[board[f]]) == 'P')
  133.     {
  134.       if (mvstr[0][0] == mvstr[0][2])    /* pawn did not eat */
  135.         {
  136.           mvstr[2][0] = mvstr[1][0] = mvstr[0][2];    /* to column */
  137.           mvstr[2][1] = mvstr[1][1] = mvstr[0][3];    /* to row */
  138.           m3p = 2;
  139.         }
  140.       else
  141.         /* pawn ate */
  142.         {
  143.           mvstr[2][0] = mvstr[1][0] = mvstr[0][0];    /* from column */
  144.           mvstr[2][1] = mvstr[1][1] = mvstr[0][2];    /* to column */
  145.           mvstr[2][2] = mvstr[0][3];
  146.           m3p = 3;        /* to row */
  147.         }
  148.       mvstr[2][m3p] = mvstr[1][2] = '\0';
  149.       if (flag & promote)
  150.         {
  151.           mvstr[0][4] = mvstr[1][2] = mvstr[2][m3p] = qxx[flag & pmask];
  152.           mvstr[1][3] = mvstr[2][m3p + 1] = mvstr[0][5] = '\0';
  153.         }
  154.     }
  155.       else
  156.     /* not a pawn */
  157.     {
  158.       mvstr[2][0] = mvstr[1][0];
  159.       mvstr[2][1] = mvstr[0][1];
  160.       mvstr[2][2] = mvstr[1][1] = mvstr[0][2];    /* to column */
  161.       mvstr[2][3] = mvstr[1][2] = mvstr[0][3];    /* to row */
  162.       mvstr[2][4] = mvstr[1][3] = '\0';
  163.       strcpy (mvstr[3], mvstr[2]);
  164.       mvstr[3][1] = mvstr[0][0];
  165.       if (flag & cstlmask)
  166.         {
  167.           if (t > f)
  168.         {
  169.           strcpy (mvstr[1], "o-o");
  170.           strcpy (mvstr[2], "O-O");
  171.         }
  172.           else
  173.         {
  174.           strcpy (mvstr[1], "o-o-o");
  175.           strcpy (mvstr[2], "O-O-O");
  176.         }
  177.         }
  178.     }
  179.     }
  180.   else
  181.     mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
  182. }
  183.  
  184.  
  185. int
  186. VerifyMove (char *s, short int iop, short unsigned int *mv)
  187.  
  188. /*
  189.    Compare the string 's' to the list of legal moves available for the
  190.    opponent. If a match is found, make the move on the board.
  191. */
  192.  
  193. {
  194.   static short pnt, tempb, tempc, tempsf, tempst, cnt;
  195.   static struct leaf xnode;
  196.   struct leaf *node;
  197.  
  198.   *mv = 0;
  199.   if (iop == 2)
  200.     {
  201.       UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  202.       return (false);
  203.     }
  204.   cnt = 0;
  205.   MoveList (opponent, 2);
  206.   pnt = TrPnt[2];
  207.   while (pnt < TrPnt[3])
  208.     {
  209.       node = &Tree[pnt++];
  210.       algbr (node->f, node->t, (short) node->flags);
  211.       if (strcmp (s, mvstr[0]) == 0 || strcmp (s, mvstr[1]) == 0 ||
  212.       strcmp (s, mvstr[2]) == 0 || strcmp (s, mvstr[3]) == 0)
  213.     {
  214.       cnt++;
  215.       xnode = *node;
  216.     }
  217.     }
  218.   if (cnt == 1)
  219.     {
  220.       MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  221.       if (SqAtakd (PieceList[opponent][0], computer))
  222.     {
  223.       UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  224.       printz ("Illegal move\n");
  225.       return (false);
  226.     }
  227.       else
  228.     {
  229.       if (iop == 1)
  230.         return (true);
  231.       UpdateDisplay (xnode.f, xnode.t, 0, (short) xnode.flags);
  232.       if ((board[xnode.t] == pawn)
  233.           || (xnode.flags & capture)
  234.           || (xnode.flags & cstlmask))
  235.         {
  236.           Game50 = GameCnt;
  237.           ZeroRPT ();
  238.         }
  239.       GameList[GameCnt].depth = GameList[GameCnt].score = 0;
  240.       GameList[GameCnt].nodes = 0;
  241.       ElapsedTime (1);
  242.       GameList[GameCnt].time = (short) et;
  243.       TimeControl.clock[opponent] -= et;
  244.       --TimeControl.moves[opponent];
  245.       *mv = (xnode.f << 8) | xnode.t;
  246.       algbr (xnode.f, xnode.t, false);
  247.       return (true);
  248.     }
  249.     }
  250. #ifdef CHESSTOOL
  251.   printz ("Illegal move\n");
  252. #else
  253.   if (cnt > 1)
  254.     ShowMessage ("Ambiguous Move!");
  255. #endif
  256.   return (false);
  257. }
  258.  
  259. void
  260. help (void)
  261. {
  262.   ClrScreen ();
  263.   printz ("CHESS command summary\n");
  264.   printz ("----------------------------------------------------------------\n");
  265.   printz ("g1f3      move from g1 to f3      quit      Exit Chess\n");
  266.   printz ("Nf3       move knight to f3       beep      on/off\n");
  267.   printz ("o-o       castle king side        easy      on/off\n");
  268.   printz ("o-o-o     castle queen side       hash      on/off\n");
  269.   printz ("bd        redraw board            reverse   board display\n");
  270.   printz ("list      game to chess.lst       book      on/off\n");
  271.   printz ("undo      undo last ply           remove    take back a move\n");
  272.   printz ("edit      edit board              force     enter game moves\n");
  273.   printz ("switch    sides with computer     both      computer match\n");
  274.   printz ("white     computer plays white    black     computer plays black\n");
  275.   printz ("depth     set search depth        clock     set time control\n");
  276.   printz ("post      principle variation     hint      suggest a move\n");
  277.   printz ("save      game to file            get       game from file\n");
  278.   printz ("random    randomize play          new       start new game\n");
  279.   printz ("----------------------------------------------------------------\n");
  280.   printz ("Computer: %-12s Opponent:            %s\n",
  281.       ColorStr[computer], ColorStr[opponent]);
  282.   printz ("Depth:    %-12d Response time:       %d sec\n",
  283.       MaxSearchDepth, Level);
  284.   printz ("Random:   %-12s Easy mode:           %s\n",
  285.       (dither) ? "ON" : "OFF", (flag.easy) ? "ON" : "OFF");
  286.   printz ("Beep:     %-12s Transposition table: %s\n",
  287.       (flag.beep) ? "ON" : "OFF", (flag.hash) ? "ON" : "OFF");
  288.   signal (SIGINT, TerminateSearch);
  289. #ifndef MSDOS  
  290.   signal (SIGQUIT, TerminateSearch);
  291. #endif /* MSDOS */  
  292. }
  293.  
  294. void
  295. EditBoard (void)
  296. /*
  297.    Set up a board position. Pieces are entered by typing the piece followed
  298.    by the location. For example, Nf3 will place a knight on square f3.
  299. */
  300.  
  301. {
  302.   short a, r, c, sq, i;
  303.   char s[80];
  304.  
  305.   ClrScreen ();
  306.   UpdateDisplay (0, 0, 1, 0);
  307.   printz (".   exit to main\n");
  308.   printz ("#   clear board\n");
  309.   printz ("c   change sides\n");
  310.   printz ("enter piece & location: \n");
  311.  
  312.   a = white;
  313.   do
  314.     {
  315.       scanz ("%s", s);
  316.       if (s[0] == '#')
  317.     for(sq = 0; sq < 64; sq++)
  318.       {
  319.         board[sq] = no_piece;
  320.         color[sq] = neutral;
  321.       }
  322.       if (s[0] == 'c' || s[0] == 'C')
  323.     a = otherside[a];
  324.       c = s[1] - 'a';
  325.       r = s[2] - '1';
  326.       if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8))
  327.     {
  328.       sq = locn (r, c);
  329.       color[sq] = a;
  330.        board[sq] = no_piece;
  331.        for(i = no_piece; i <= king; i++)
  332.          if ((s[0] == pxx[i]) || (s[0] == qxx[i]))
  333.            {
  334.              board[sq] = i;
  335.              break;
  336.            }
  337.     }
  338.   } while (s[0] != '.');
  339.   for (sq = 0; sq < 64; sq++)
  340.     Mvboard[sq] = (board[sq] != Stboard[sq]) ? 10 : 0;
  341.   GameCnt = 0;
  342.   Game50 = 1;
  343.   ZeroRPT ();
  344.   InitializeStats ();
  345.   ClrScreen ();
  346.   UpdateDisplay (0, 0, 1, 0);
  347. }
  348.  
  349. void
  350. SetupBoard (void)
  351.  
  352. /*
  353.    Compatibility with Unix chess and the nchesstool.
  354.    Set up a board position. Eight lines of eight characters are used
  355.    to setup the board. a8-h8 is the first line.
  356.    Black pieces are  represented  by  uppercase characters.
  357. */
  358.  
  359. {
  360.   short r, c, sq, i;
  361.   char ch;
  362.   char s[80];
  363.  
  364.   NewGame ();
  365.  
  366.   gets (s);            /* skip "setup" command */
  367.   for (r = 7; r >= 0; r--)
  368.     {
  369.       gets (s);
  370.       for (c = 0; c <= 7; c++)
  371.     {
  372.       ch = s[c];
  373.       sq = locn (r, c);
  374.       color[sq] = neutral;
  375.       board[sq] = no_piece;
  376.        for(i = no_piece; i <= king; i++)
  377.         if (ch == pxx[i])
  378.           {
  379.         color[sq] = black;
  380.         board[sq] = i;
  381.         break;
  382.           }
  383.         else
  384.           if (ch == qxx[i])
  385.         {
  386.           color[sq] = white;
  387.           board[sq] = i;
  388.           break;
  389.         }
  390.     }      
  391.     }
  392.   for (sq = 0; sq < 64; sq++)
  393.     Mvboard[sq] = (board[sq] != Stboard[sq]) ? 10 : 0;
  394.   InitializeStats ();
  395.   ClrScreen ();
  396.   UpdateDisplay (0, 0, 1, 0);
  397.   printz ("Setup successful\n");
  398. }
  399.  
  400. void
  401. ShowDepth (char ch)
  402. {
  403. #ifdef MSDOS
  404.   ch++;                    /* shut up the compiler */
  405. #endif /* MSDOS */
  406. }
  407.  
  408. void
  409. ShowResults (short int score, short unsigned int *bstline, char ch)
  410. {
  411.   register int i;
  412.   if (flag.post)
  413.     {
  414.       fprintf (stderr, "%2d%c %6d %4ld %8ld  ", Sdepth, ch, score, et, NodeCnt);
  415.       for (i = 1; bstline[i] > 0; i++)
  416.     {
  417.       if ((i > 1) && (i % 8 == 1))
  418.         fprintf (stderr, "\n                          ");
  419.       algbr ((short) (bstline[i] >> 8), (short) (bstline[i] & 0xFF), false);
  420.       fprintf (stderr, "%5s ", mvstr[0]);
  421.     }
  422.       fprintf (stderr, "\n");
  423.     }
  424. }
  425.  
  426. void
  427. SearchStartStuff (short int side)
  428. {
  429.   signal (SIGINT, TerminateSearch);
  430. #ifndef MSDOS  
  431.   signal (SIGQUIT, TerminateSearch);
  432. #endif /* MSDOS */  
  433.   if (flag.post)
  434.     {
  435.       fprintf (stderr, "\nMove# %d    Target= %ld    Clock: %ld\n",
  436.            TCmoves - TimeControl.moves[side] + 1,
  437.            ResponseTime, TimeControl.clock[side]);
  438.     }
  439. }
  440.  
  441. void
  442. OutputMove (void)
  443. { int auto_prom;  /***** auto.c addition *****/
  444.  
  445.   if(! autoplay) printz ("%d.  ... %s\n", ++mycnt1, mvstr[0]);
  446.   if (root->flags & draw)
  447.     {
  448.       printz ("Draw\n");
  449.       ExitChess ();
  450.     }
  451.   
  452.   /*** win/lose moved from here: see below ***/
  453.   
  454.   if (flag.post)
  455.     {
  456.       fprintf (stderr, "Nodes= %ld  Eval= %ld  Rate= %ld  ",
  457.            NodeCnt, EvalNodes, evrate);
  458.       fprintf (stderr, "Hash/Coll= %ld/%ld\n",
  459.            HashCnt, HashCol);
  460.     }
  461.  
  462.   UpdateDisplay (root->f, root->t, 0, root->flags);
  463.   
  464.   /***** auto alteration *****/
  465.   if(autoplay)
  466.   {  if(computer==white) printf("My move is: %d. %s\n",MVNUM,mvstr[0]);
  467.      else printf("My move is: %d. ... %s\n",MVNUM,mvstr[0]);
  468.   }     
  469.   else fprintf (stderr, "My move is: %s\n", mvstr[0]);
  470.   
  471.   /*** win/lose moved to here: see above ***/
  472.   /*
  473.   if (root->score == -9999)
  474.     {
  475.       printz ("%s\n", ColorStr[opponent]);
  476.       ExitChess ();
  477.     }
  478.   if (root->score == 9998)
  479.     {
  480.       printz ("%s\n", ColorStr[computer]);
  481.       ExitChess ();
  482.     }
  483.   */
  484.  
  485.   /***** auto.c addition *****/
  486.   if(autoplay)
  487.     { 
  488.       if (root->flags & promote)
  489.         auto_prom = 6 - (root->flags & pmask);
  490.       else auto_prom = 0;            
  491.       /*   auto_makemove(root->f,root->t,auto_prom); */
  492.       auto_makemove( auto_prom*4096 + (root->t)*64 + root->f);
  493.     }
  494.  
  495.   if (flag.beep)
  496.     printz ("%c", 7);
  497.  
  498.   if (root->flags & draw)
  499.     fprintf (stderr, "Drawn game!\n");
  500.   else if (root->score == -9999)
  501.     fprintf (stderr, "opponent mates!\n");
  502.   else if (root->score == 9998)
  503.     fprintf (stderr, "computer mates!\n");
  504.   else if (root->score < -9000)
  505.     fprintf (stderr, "opponent will soon mate!\n");
  506.   else if (root->score > 9000)
  507.     fprintf (stderr, "computer will soon mate!\n");
  508.     
  509.   /*** mcs: win/lose added here ***/
  510.   if (root->score == -9999)
  511.     {
  512.       printz ("%s\n", ColorStr[opponent]);
  513.       ExitChess ();
  514.     }
  515.   if (root->score == 9998)
  516.     {
  517.       printz ("%s\n", ColorStr[computer]);
  518.       ExitChess ();
  519.     }
  520.  
  521. }
  522.  
  523. void
  524. ElapsedTime (short int iop)
  525.                
  526.  
  527. /*
  528.    Determine the time that has passed since the search was started. If the
  529.    elapsed time exceeds the target (ResponseTime+ExtraTime) then set timeout
  530.    to true which will terminate the search.
  531. */
  532.  
  533. {
  534.   if (ahead)
  535.     {
  536. #ifndef MSDOS  
  537.       long nchar;
  538.       ioctl(0, FIONREAD, &nchar);
  539.       if (nchar)
  540. #else    
  541.       if (kbhit())
  542. #endif /* MSDOS */
  543.     {
  544.       flag.timeout = true;
  545.       flag.bothsides = false;
  546.     }
  547.     }
  548.   et = time ((long *) 0) - time0;
  549.   if (et < 0)
  550.     et = 0;
  551.   ETnodes += 50;
  552.   if (et > et0 || iop == 1)
  553.     {
  554.       if (et > ResponseTime + ExtraTime && Sdepth > 1)
  555.     flag.timeout = true;
  556.       et0 = et;
  557.       if (iop == 1)
  558.     {
  559.       time0 = time ((long *) 0);
  560.       et0 = 0;
  561.     }
  562.       if (et > 0)
  563.     /* evrate used to be Nodes / cputime I dont` know why */
  564.     evrate = NodeCnt / (et + ft);
  565.       else
  566.     evrate = 0;
  567.       ETnodes = NodeCnt + 50;
  568.     }
  569. }
  570.  
  571. void
  572. SetTimeControl (void)
  573. {
  574.   if (TCflag)
  575.     {
  576.       TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
  577.       TimeControl.clock[white] = TimeControl.clock[black] = 60L * TCminutes;
  578.     }
  579.   else
  580.     {
  581.       TimeControl.moves[white] = TimeControl.moves[black] = 0;
  582.       TimeControl.clock[white] = TimeControl.clock[black] = 0;
  583.       Level = 60L * TCminutes;
  584.     }
  585.   et = 0;
  586.   ElapsedTime (1);
  587. }
  588.  
  589. void
  590. ClrScreen (void)
  591. {
  592. #ifndef CHESSTOOL
  593.   printz ("\n");
  594. #endif
  595. }
  596.  
  597. void
  598. UpdateDisplay (short int f, short int t, short int redraw, short int isspec)
  599. {
  600. #ifndef CHESSTOOL
  601.   short r, c, l;
  602.   if (redraw)
  603.     {
  604.       printz ("\n");
  605.       for (r = 7; r >= 0; r--)
  606.     {
  607.       for (c = 0; c <= 7; c++)
  608.         {
  609.           if (flag.reverse)
  610.         l = locn (7 - r, 7 - c);
  611.           else
  612.         l = locn (r, c);
  613.           if (color[l] == neutral)
  614.         printz (" -");
  615.           else if (color[l] == white)
  616.         printz (" %c", qxx[board[l]]);
  617.           else
  618.         printz (" %c", pxx[board[l]]);
  619.         }
  620.       printz ("\n");
  621.     }
  622.       printz ("\n");
  623.     }
  624. #endif /* CHESSTOOL */
  625. #ifdef MSDOS
  626.   f++; t++; isspec++;            /* shut up the compiler */
  627. #endif /* MSDOS */
  628. }
  629.  
  630. void
  631. GetGame (void)
  632. {
  633.   FILE *fd;
  634.   char fname[256];
  635.   int c;
  636.   short sq;
  637.   unsigned short m;
  638.  
  639.   printz ("Enter file name: ");
  640.   scanz ("%s", fname);
  641.   if (fname[0] == '\0')
  642.     strcpy (fname, "chess.000");
  643.   if ((fd = fopen (fname, "r")) != NULL)
  644.     {
  645.       fscanf (fd, "%hd%hd%hd", &computer, &opponent, &Game50);
  646.       fscanf (fd, "%hd%hd", &castld[white], &castld[black]);
  647.       fscanf (fd, "%hd%hd", &TCflag, &OperatorTime);
  648.       fscanf (fd, "%ld%ld%hd%hd",
  649.           &TimeControl.clock[white], &TimeControl.clock[black],
  650.           &TimeControl.moves[white], &TimeControl.moves[black]);
  651.       for (sq = 0; sq < 64; sq++)
  652.     {
  653.       fscanf (fd, "%hd%hd", &m, &Mvboard[sq]);
  654.       board[sq] = (m >> 8);
  655.       color[sq] = (m & 0xFF);
  656.       if (color[sq] == 0)
  657.         color[sq] = neutral;
  658.       else
  659.         --color[sq];
  660.     }
  661.       GameCnt = 0;
  662.       c = '?';
  663.       while (c != EOF)
  664.     {
  665.       ++GameCnt;
  666.       c = fscanf (fd, "%hd%hd%hd%ld%hd%hd%hd", &GameList[GameCnt].gmove,
  667.               &GameList[GameCnt].score, &GameList[GameCnt].depth,
  668.               &GameList[GameCnt].nodes, &GameList[GameCnt].time,
  669.               &GameList[GameCnt].piece, &GameList[GameCnt].color);
  670.       if (GameList[GameCnt].color == 0)
  671.         GameList[GameCnt].color = neutral;
  672.       else
  673.         --GameList[GameCnt].color;
  674.     }
  675.       GameCnt--;
  676.       if (TimeControl.clock[white] > 0)
  677.     TCflag = true;
  678.       computer--;
  679.       opponent--;
  680.     }
  681.   fclose (fd);
  682.   InitializeStats ();
  683.   UpdateDisplay (0, 0, 1, 0);
  684.   Sdepth = 0;
  685. }
  686.  
  687. void
  688. SaveGame (void)
  689. {
  690.   FILE *fd;
  691.   char fname[256];
  692.   short sq, i, c;
  693.  
  694.   printz ("Enter file name: ");
  695.   scanz ("%s", fname);
  696.  
  697.   if (fname[0] == '\0')
  698.     strcpy (fname, "chess.000");
  699.   if ((fd = fopen (fname, "w")) != NULL)
  700.     {
  701.       fprintf (fd, "%d %d %d\n", computer + 1, opponent + 1, Game50);
  702.       fprintf (fd, "%d %d\n", castld[white], castld[black]);
  703.       fprintf (fd, "%d %d\n", TCflag, OperatorTime);
  704.       fprintf (fd, "%ld %ld %d %d\n",
  705.            TimeControl.clock[white], TimeControl.clock[black],
  706.            TimeControl.moves[white], TimeControl.moves[black]);
  707.       for (sq = 0; sq < 64; sq++)
  708.     {
  709.       if (color[sq] == neutral)
  710.         c = 0;
  711.       else
  712.         c = color[sq] + 1;
  713.       fprintf (fd, "%d %d\n", 256 * board[sq] + c, Mvboard[sq]);
  714.     }
  715.       for (i = 1; i <= GameCnt; i++)
  716.     {
  717.       if (GameList[i].color == neutral)
  718.         c = 0;
  719.       else
  720.         c = GameList[i].color + 1;
  721.       fprintf (fd, "%d %d %d %ld %d %d %d\n",
  722.            GameList[i].gmove, GameList[i].score, GameList[i].depth,
  723.            GameList[i].nodes, GameList[i].time,
  724.            GameList[i].piece, c);
  725.     }
  726.       fclose (fd);
  727.       printz ("Game saved on file: %s", fname);
  728.     }
  729.   else
  730.     printz ("Could not open file: %s", fname);
  731. }
  732.  
  733. void
  734. ListGame (void)
  735. {
  736.   FILE *fd;
  737.   short i, f, t;
  738.   fd = fopen ("chess.lst", "w");
  739.   fprintf (fd, "\n");
  740.   fprintf (fd, "       score  depth   nodes  time         ");
  741.   fprintf (fd, "       score  depth   nodes  time\n");
  742.   for (i = 1; i <= GameCnt; i++)
  743.     {
  744.       f = GameList[i].gmove >> 8;
  745.       t = (GameList[i].gmove & 0xFF);
  746.       algbr (f, t, false);
  747.       if ((i % 2) == 0)
  748.     fprintf (fd, "         ");
  749.       else
  750.     fprintf (fd, "\n");
  751.       fprintf (fd, "%5s  %5d     %2d %7ld %5d", mvstr[0],
  752.            GameList[i].score, GameList[i].depth,
  753.            GameList[i].nodes, GameList[i].time);
  754.     }
  755.   fprintf (fd, "\n\n");
  756.   fclose (fd);
  757. }
  758.  
  759. void
  760. Undo (void)
  761. /*
  762.    Undo the most recent half-move.
  763. */
  764.  
  765. {
  766.   short f, t;
  767.   f = GameList[GameCnt].gmove >> 8;
  768.   t = GameList[GameCnt].gmove & 0xFF;
  769.   if (board[t] == king && distance (t, f) > 1)
  770.     (void) castle (GameList[GameCnt].color, f, t, 2);
  771.   else
  772.     {
  773.       /* Check for promotion: */
  774.       if ((row (f) == 6 && row (t) == 7) || (row (f) == 1 && row (t) == 0))
  775.     {
  776.       int g, from = f;
  777.       for (g = GameCnt - 1; g > 0; g--)
  778.         if (GameList[g].gmove & 0xFF == from)
  779.           from = GameList[g].gmove >> 8;
  780.       if (row (from) == 1 || row (from) == 6)
  781.         board[t] = pawn;
  782.     }
  783.  
  784.       board[f] = board[t];
  785.       color[f] = color[t];
  786.       board[t] = GameList[GameCnt].piece;
  787.       color[t] = GameList[GameCnt].color;
  788.       if (color[t] != neutral)
  789.     Mvboard[t]--;
  790.       Mvboard[f]--;
  791.     }
  792.   if (TCflag)
  793.     ++TimeControl.moves[color[f]];
  794.   GameCnt--;
  795.   computer = otherside[computer];
  796.   opponent = otherside[opponent];
  797.   flag.mate = false;
  798.   Sdepth = 0;
  799.   UpdateDisplay (0, 0, 1, 0);
  800.   InitializeStats ();
  801. }
  802.  
  803. void
  804. ShowMessage (char *s)
  805. {
  806.   fprintf (stderr, "%s\n", s);
  807. }
  808.  
  809. void
  810. ShowSidetomove (void)
  811. {
  812. }
  813.  
  814. void
  815. PromptForMove (void)
  816. {
  817. /**** auto.c alteration *****/
  818. /* #ifndef CHESSTOOL */
  819.   printz ("\nYour move is? ");
  820. /* #endif  */
  821. /* CHESSTOOL */
  822. }
  823.  
  824.  
  825. void
  826. ShowCurrentMove (short int pnt, short int f, short int t)
  827. {
  828. #ifdef MSDOS
  829.   f++; t++; pnt++;            /* shut up the compiler */
  830. #endif /* MSDOS */
  831. }
  832.  
  833. void
  834. ChangeAlphaWindow (void)
  835. {
  836.   printz ("window: ");
  837.   scanz ("%hd", &Awindow);
  838. }
  839.  
  840. void
  841. ChangeBetaWindow (void)
  842. {
  843.   printz ("window: ");
  844.   scanz ("%hd", &Bwindow);
  845. }
  846.  
  847. void
  848. GiveHint (void)
  849. {
  850.   algbr ((short) (hint >> 8), (short) (hint & 0xFF), false);
  851.   fprintf (stderr, "Hint: %s\n", mvstr[0]);
  852. }
  853.  
  854. void
  855. SelectLevel (void)
  856. {
  857.   printz ("Enter #moves #minutes: ");
  858.   scanz ("%hd %hd", &TCmoves, &TCminutes);
  859.   printz ("Operator time= ");
  860.   scanz ("%hd", &OperatorTime);
  861.   TCflag = (TCmoves > 1);
  862.   SetTimeControl ();
  863. }
  864.  
  865. void
  866. ChangeSearchDepth (void)
  867. {
  868.   printz ("depth= ");
  869.   scanz ("%hd", &MaxSearchDepth);
  870. }
  871.  
  872. void
  873. SetContempt (void)
  874. {
  875.   printz ("contempt= ");
  876.   scanz ("%hd", &contempt);
  877. }
  878.  
  879. void
  880. ChangeXwindow (void)
  881. {
  882.   printz ("xwndw= ");
  883.   scanz ("%hd", &xwndw);
  884. }
  885.  
  886. void
  887. TestSpeed(void (*f) (short int side, short int ply))
  888. {
  889.   short i;
  890.   long cnt, rate, t1, t2;
  891.   
  892.   t1 = time (0);
  893.   for (i = 0; i < 10000; i++)
  894.     {
  895.       f (opponent, 2);
  896.     }
  897.   t2 = time (0);
  898.   cnt = 10000L * (TrPnt[3] - TrPnt[2]);
  899.   rate = cnt / (t2 - t1);
  900.   printz ("Nodes= %ld Nodes/sec= %ld\n", cnt, rate);
  901. }
  902.  
  903.  
  904. void
  905. InputCommand (void)
  906. /*
  907.    Process the users command. If easy mode is OFF (the computer is thinking
  908.    on opponents time) and the program is out of book, then make the 'hint'
  909.    move on the board and call SelectMove() to find a response. The user
  910.    terminates the search by entering ^C (quit siqnal) before entering a
  911.    command. If the opponent does not make the hint move, then set Sdepth to
  912.    zero.
  913. */
  914.  
  915. {
  916.   int i;
  917.   short ok, tmp;
  918.   unsigned short mv;
  919.   char s[80];
  920.   
  921.   int from_sq, to_sq, prom_pce, move;  /***** auto.c additions *****/
  922.  
  923.   ok = flag.quit = false;
  924.   player = opponent;
  925.   ft = 0;
  926.   if (hint > 0 && !flag.easy && Book == NULL)
  927.     {
  928.       fflush (stdout);
  929.       time0 = time ((long *) 0);
  930.       algbr ((short) hint >> 8, (short) hint & 0xFF, false);
  931.       strcpy (s, mvstr[0]);
  932.       tmp = epsquare;
  933.       if (flag.post)
  934.     GiveHint ();
  935.       if (VerifyMove (s, 1, &mv))
  936.     {
  937.       ahead = 1;
  938.       SelectMove (computer, 2);
  939.       VerifyMove (mvstr[0], 2, &mv);
  940.       if (Sdepth > 0)
  941.         Sdepth--;
  942.     }
  943.       ft = time ((long *) 0) - time0;
  944.       epsquare = tmp;
  945.     }
  946.   ahead = 0;
  947.   while (!(ok || flag.quit))
  948.     {
  949.       if(! autoplay)
  950.       {  PromptForMove ();
  951.          i = scanz ("%s", s);
  952.          if (i == EOF || s[0] == 0)
  953.        ExitChess ();
  954.       }
  955.            
  956.       player = opponent;
  957.       
  958.       /***** auto.c addition *****/  
  959.       if(autoplay)
  960.       { show_autoprompt();
  961.         if(! auto_readmove(&move))
  962.         {   from_sq = move & 63;
  963.             to_sq = (move >> 6) & 63;
  964.             prom_pce = move >>12;
  965.             ok = m_VerifyMove(from_sq, to_sq, prom_pce, 0, &mv);
  966.             if(computer==black) 
  967.             {  printf ("Input move: %d. %s\n",MVNUM,mvstr[0]);
  968.             }
  969.             else printf("Input move: %d.  ... %s\n",MVNUM,mvstr[0]);
  970.         }
  971.         sleep(1);
  972.         continue;
  973.       }
  974.       if(strcmp (s, "autow") == 0) ok = begin_autow(); 
  975.       if(strcmp (s, "autob") == 0) ok = begin_autob();     
  976.       if(strcmp (s, "notauto") == 0) autoplay=0;
  977.       
  978.       if(strcmp (s, "mcs") == 0) 
  979.       {  printf("Level= %d TCmoves=%d TCminutes=%d\n",Level,TCmoves,TCminutes);
  980.          printf("TCflag=%d\n",TCflag);
  981.       } 
  982.       /*****/
  983.                
  984.       if (strcmp (s, "bd") == 0)
  985.     {
  986.       ClrScreen ();
  987.       UpdateDisplay (0, 0, 1, 0);
  988.     }
  989.       else if (strcmp (s, "alg") == 0) /* noop */ ;
  990.       else if ((strcmp (s, "quit") == 0) || (strcmp(s, "exit") == 0))
  991.     flag.quit = true;
  992.       else if (strcmp (s, "post") == 0)
  993.     flag.post = !flag.post;
  994.       else if ((strcmp (s, "set") == 0) || (strcmp(s, "edit") == 0))
  995.     EditBoard ();
  996.       else if (strcmp (s, "setup") == 0)
  997.     SetupBoard ();
  998.       else if (strcmp (s, "go") == 0)
  999.     ok = true;
  1000.       else if (strcmp (s, "help") == 0)
  1001.     help ();
  1002.       else if (strcmp (s, "force") == 0)
  1003.     flag.force = !flag.force;
  1004.       else if (strcmp (s, "book") == 0)
  1005.     Book = NULL;
  1006.       else if (strcmp (s, "new") == 0)
  1007.     NewGame ();
  1008.       else if (strcmp (s, "list") == 0)
  1009.     ListGame ();
  1010.       else if (strcmp (s, "level") == 0 || strcmp (s, "clock") == 0)
  1011.     SelectLevel ();
  1012.       else if (strcmp (s, "hash") == 0)
  1013.     flag.hash = !flag.hash;
  1014.       else if (strcmp (s, "beep") == 0)
  1015.     flag.beep = !flag.beep;
  1016.       else if (strcmp (s, "Awindow") == 0)
  1017.     ChangeAlphaWindow ();
  1018.       else if (strcmp (s, "Bwindow") == 0)
  1019.     ChangeBetaWindow ();
  1020.       else if (strcmp (s, "rcptr") == 0)
  1021.     flag.rcptr = !flag.rcptr;
  1022.       else if (strcmp (s, "hint") == 0)
  1023.     GiveHint ();
  1024.       else if (strcmp (s, "both") == 0)
  1025.     {
  1026.       flag.bothsides = !flag.bothsides;
  1027.       Sdepth = 0;
  1028.       ElapsedTime (1);
  1029.       SelectMove (opponent, 1);
  1030.       ok = true;
  1031.     }
  1032.       else if (strcmp (s, "reverse") == 0)
  1033.     {
  1034.       flag.reverse = !flag.reverse;
  1035.       ClrScreen ();
  1036.       UpdateDisplay (0, 0, 1, 0);
  1037.     }
  1038.       else if (strcmp (s, "switch") == 0)
  1039.     {
  1040.       computer = otherside[computer];
  1041.       opponent = otherside[opponent];
  1042.       flag.force = false;
  1043.       Sdepth = 0;
  1044.       ok = true;
  1045.     }
  1046.       else if (strcmp (s, "white") == 0 || strcmp (s, "first") == 0)
  1047.     {
  1048.       computer = white;
  1049.       opponent = black;
  1050.       ok = true;
  1051.       flag.force = false;
  1052.       Sdepth = 0;
  1053.     }
  1054.       else if (strcmp (s, "black") == 0)
  1055.     {
  1056.       computer = black;
  1057.       opponent = white;
  1058.       ok = true;
  1059.       flag.force = false;
  1060.       Sdepth = 0;
  1061.     }
  1062.       else if (strcmp (s, "undo") == 0 && GameCnt > 0)
  1063.     Undo ();
  1064.       else if (strcmp (s, "remove") == 0 && GameCnt > 1)
  1065.     {
  1066.       Undo ();
  1067.       Undo ();
  1068.     }
  1069.       else if (strcmp (s, "get") == 0)
  1070.     GetGame ();
  1071.       else if (strcmp (s, "save") == 0)
  1072.     SaveGame ();
  1073.       else if (strcmp (s, "depth") == 0)
  1074.     ChangeSearchDepth ();
  1075.       else if (strcmp (s, "random") == 0)
  1076.     dither = 6;
  1077.       else if (strcmp (s, "easy") == 0)
  1078.     flag.easy = !flag.easy;
  1079.       else if (strcmp (s, "contempt") == 0)
  1080.     SetContempt ();
  1081.       else if (strcmp (s, "xwndw") == 0)
  1082.     ChangeXwindow ();
  1083.       else if (strcmp (s, "test") == 0)
  1084.     {
  1085.           ShowMessage("Testing MoveList Speed");
  1086.       TestSpeed (MoveList);
  1087.           ShowMessage("Testing CaptureList Speed");
  1088.       TestSpeed (CaptureList);
  1089.     }
  1090.       else
  1091.     {
  1092.       if(! autoplay) ok = VerifyMove (s, 0, &mv);
  1093.       if (ok && mv != hint)
  1094.         {
  1095.           Sdepth = 0;
  1096.           ft = 0;
  1097.         }
  1098.     }
  1099.     }
  1100.  
  1101.   ElapsedTime (1);
  1102.   if (flag.force)
  1103.     {
  1104.       computer = opponent;
  1105.       opponent = otherside[computer];
  1106.     }
  1107.     
  1108. #ifdef CHESSTOOL
  1109. /***** auto alteration *****/
  1110. if(! autoplay) printf ("%d. %s\n", ++mycnt2, s);
  1111. #endif /* CHESSTOOL */
  1112.   signal (SIGINT, TerminateSearch);
  1113. #ifndef MSDOS  
  1114.   signal (SIGQUIT, TerminateSearch);
  1115. #endif /* MSDOS */  
  1116. }
  1117.